home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / TCAP.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  15KB  |  593 lines

  1. /*    tcap:    Unix V5, SUN OS, SCO XENIX, V7 and BS4.2 Termcap video driver
  2.         for MicroEMACS 3.12
  3.  
  4.          12-10-88 - Modifications made by Guy Turcotte to accomodate
  5.                     SunOS V4.0 and Xenix V2.2.1 :
  6.  
  7.                   SunOS mods:
  8.                   
  9.                   o p_seq field of TBIND struct augmented to 10 chars
  10.                     to take into account longer definitions for keys
  11.                     (some Sun's keys definitions need at least 7 chars...)
  12.                     as such, the code in get1key has been modified to take
  13.                     care of the longer p_seq string.
  14.  
  15.                   o tcapopen modified to take care of the tgetstr problem
  16.                     (returns NULL on undefined keys instead of a valid
  17.                     string pointer...)
  18.  
  19.                   o The timout algorithm of get1key has been modified to
  20.                     take care of the following select() function problem:
  21.                     if some chars are already in the terminal buffer before
  22.                     select is called and no others char appears on the terminal,
  23.                     it will timeout anyway... (maybe a feature of SunOs V4.0)
  24.  
  25.                   Xenix mods:
  26.  
  27.                   o The first two points indicated above are applicable for
  28.                     the Xenix OS
  29.  
  30.                   o With my current knowledge, I can't find a clean solution
  31.                     to the timeout problem of the get1key function
  32.                     under Xenix. I modified the code to get rid of the BSD code 
  33.                     (via the #if directive) and use the Xenix nap() and rdchk()
  34.                     functions to 
  35.                     make a 1/30 second wait. Seems to work as long as there is
  36.                     not to much of activity from other processes on the system.
  37.                     (The link command of the makefile must be modified to
  38.                     link with the x library... you must add the option -lx)
  39.  
  40.                   o The input.c file has been modified to not include the
  41.                     get1key function defined there in the case of USG. The
  42.                     #if directive preceeding the get1key definition has been
  43.                     modified from:
  44.  
  45.                      #if (V7 == 0) && (BSD == 0)
  46.  
  47.                     to:
  48.  
  49.                      #if (V7 == 0) && (BSD == 0) && (USG == 0)
  50.                      
  51.                   o The following lines define the new termcap entry for
  52.                     the ansi kind of terminal: it permits the use of functions
  53.                     keys F1 .. F10 and keys HOME,END,PgUp,PgDn on the IBM PC
  54.                     keyboard (the last 3 lines of the definition have been
  55.                     added):
  56.  
  57.  li|ansi|Ansi standard crt:\
  58.      :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%d;%dH:co#80:\
  59.      :dc=\E[P:dl=\E[M:do=\E[B:bt=\E[Z:ei=:ho=\E[H:ic=\E[@:im=:li#25:\
  60.      :nd=\E[C:pt:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:up=\E[A:\
  61.      :kb=^h:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:eo:sf=\E[S:sr=\E[T:\
  62.      :GS=\E[12m:GE=\E[10m:GV=\63:GH=D:\
  63.      :GC=E:GL=\64:GR=C:RT=^J:G1=?:G2=Z:G3=@:G4=Y:GU=A:GD=B:\
  64.      :CW=\E[M:NU=\E[N:RF=\E[O:RC=\E[P:\
  65.      :WL=\E[S:WR=\E[T:CL=\E[U:CR=\E[V:\
  66.      :HM=\E[H:EN=\E[F:PU=\E[I:PD=\E[G:\
  67.      :k1=\E[M:k2=\E[N:k3=\E[O:k4=\E[P:k5=\E[Q:\
  68.      :k6=\E[R:k7=\E[S:k8=\E[T:k9=\E[U:k0=\E[V:\
  69.      :kh=\E[H:kH=\E[F:kA=\E[L:kN=\E[G:kP=\E[I:
  70.                     
  71. */
  72.  
  73. #define termdef 1            /* don't define "term" external */
  74.  
  75. #include <stdio.h>
  76. #include    "estruct.h"
  77. #include    "eproto.h"
  78. #include    "edef.h"
  79. #include    "elang.h"
  80.  
  81. #if TERMCAP
  82.  
  83. #if    USG | AUX | HPUX8 | HPUX9 | SMOS
  84. #include    <time.h>
  85. #endif
  86. #if    BSD | V7
  87. #include    <sys/types.h>
  88. #include    <sys/time.h>
  89. #endif
  90.  
  91. #define MARGIN    8
  92. #define SCRSIZ    64
  93. #define NPAUSE    10            /* # times thru update to pause */
  94. #define BEL    0x07
  95. #define ESC    0x1B
  96.  
  97. /*    Termcap Sequence definitions    */
  98.  
  99. typedef struct TBIND {
  100.     char p_name[4]; /* sequence name */
  101.     short p_code;    /* resulting keycode of sequence */
  102.     char p_seq[10];    /* terminal escape sequence */
  103. } TBIND;
  104.  
  105. TBIND ttable[] = {
  106.     "bt",    SHFT | CTRL | 'i',    "",    /* backtab */
  107.     "k1",    SPEC | '1',        "",    /* function key 1 */
  108.     "k2",    SPEC | '2',        "",    /* function key 2 */
  109.     "k3",    SPEC | '3',        "",    /* function key 3 */
  110.     "k4",    SPEC | '4',        "",    /* function key 4 */
  111.     "k5",    SPEC | '5',        "",    /* function key 5 */
  112.     "k6",    SPEC | '6',        "",    /* function key 6 */
  113.     "k7",    SPEC | '7',        "",    /* function key 7 */
  114.     "k8",    SPEC | '8',        "",    /* function key 8 */
  115.     "k9",    SPEC | '9',        "",    /* function key 9 */
  116.     "k0",    SPEC | '0',        "",    /* function key 10 */
  117.     "kA",    CTRL | 'O',        "",    /* insert line */
  118.     "kb",    CTRL | 'H',        "",    /* backspace */
  119.     "kC",    CTRL | 'L',        "",    /* clear screen */
  120.     "kD",    SPEC | 'D',        "",    /* delete character */
  121.     "kd",    SPEC | 'N',        "",    /* down cursor */
  122.     "kE",    CTRL | 'K',        "",    /* clear to end of line */
  123.     "kF",    CTRL | 'V',        "",    /* scroll down */
  124.     "kH",    SPEC | '>',        "",    /* home down [END?] key */
  125.     "kh",    SPEC | '<',        "",    /* home */
  126.     "kI",    SPEC | 'C',        "",    /* insert character */
  127.     "kL",    CTRL | 'K',        "",    /* delete line */
  128.     "kl",    SPEC | 'B',        "",    /* left cursor */
  129.     "kN",    SPEC | 'V',        "",    /* next page */
  130.     "kP",    SPEC | 'Z',        "",    /* previous page */
  131.     "kR",    CTRL | 'Z',        "",    /* scroll down */
  132.     "kr",    SPEC | 'F',        "",    /* right cursor */
  133.     "ku",    SPEC | 'P',        "",    /* up cursor */
  134. #if    SMOS
  135.     "ka",    SPEC | 'J',        "",    /* function key 11*/
  136.     "F1",    SPEC | 'K',        "",    /* function key 12*/
  137.     "F2",    SPEC | 'L',        "",    /* function key 13*/
  138.     "F3",    SPEC | 'M',        "",    /* function key 14*/
  139.     "F4",    SPEC | 'N',        "",    /* function key 15*/
  140.     "F5",    SPEC | 'O',        "",    /* function key 16*/
  141.     "F6",    SHFT | SPEC | '1',    "",    /* S-function key 1 */
  142.     "F7",    SHFT | SPEC | '2',    "",    /* S-function key 2 */
  143.     "F8",    SHFT | SPEC | '3',    "",    /* S-function key 3 */
  144.     "F9",    SHFT | SPEC | '4',    "",    /* S-function key 4 */
  145.     "FA",    SHFT | SPEC | '5',    "",    /* S-function key 5 */
  146.     "FB",    SHFT | SPEC | '6',    "",    /* S-function key 6 */
  147.     "FC",    SHFT | SPEC | '7',    "",    /* S-function key 7 */
  148.     "FD",    SHFT | SPEC | '8',    "",    /* S-function key 8 */
  149.     "FE",    SHFT | SPEC | '9',    "",    /* S-function key 9 */
  150.     "FF",    SHFT | SPEC | '0',    "",    /* S-function key 10*/
  151.     "FG",    SHFT | SPEC | 'J',    "",    /* S-function key 11*/
  152.     "FH",    SHFT | SPEC | 'K',    "",    /* S-function key 12*/
  153.     "FI",    SHFT | SPEC | 'L',    "",    /* S-function key 13*/
  154.     "FJ",    SHFT | SPEC | 'M',    "",    /* S-function key 14*/
  155.     "FK",    SHFT | SPEC | 'N',    "",    /* S-function key 15*/
  156.     "FL",    SHFT | SPEC | 'O',    "",    /* S-function key 16*/
  157. #endif
  158. };
  159.  
  160. #define    NTBINDS    sizeof(ttable)/sizeof(TBIND)
  161.  
  162. extern int    ttopen();
  163. extern int    ttgetc();
  164. extern int    ttputc();
  165. extern int    tgetnum();
  166. extern int    ttflush();
  167. extern int    ttclose();
  168. extern int    tcapkopen();
  169. extern int    tcapkclose();
  170. extern int    tcapgetc();
  171. extern int    tcapmove();
  172. extern int    tcapeeol();
  173. extern int    tcapeeop();
  174. extern int    tcapbeep();
  175. extern int    tcaprev();
  176. extern int    tcapcres();
  177. extern int    tcapopen();
  178. extern int    tcapclose();
  179. extern int    tput();
  180. extern char    *tgoto();
  181. #if    COLOR
  182. extern    int    tcapfcol();
  183. extern    int    tcapbcol();
  184. #endif
  185.  
  186. #define TCAPSLEN 1024
  187. char tcapbuf[TCAPSLEN];
  188. char *UP, PC, *CM, *CE, *CL, *SO, *SE, *IS, *KS, *KE;
  189.  
  190. TERM term = {
  191.     0, 0, 0, 0,    /* these four values are set dynamically at open time */
  192.     0, 0,
  193.     MARGIN,
  194.     SCRSIZ,
  195.     NPAUSE,
  196.     tcapopen,
  197.     tcapclose,
  198.     tcapkopen,
  199.     tcapkclose,
  200.     tcapgetc,
  201.     ttputc,
  202.     ttflush,
  203.     tcapmove,
  204.     tcapeeol,
  205.     tcapeeop,
  206.     tcapclrd,
  207.     tcapbeep,
  208.     tcaprev,
  209.     tcapcres
  210. #if    COLOR
  211.     , tcapfcol,
  212.     tcapbcol
  213. #endif
  214. };
  215.  
  216. /*    input buffers and pointers    */
  217.  
  218. #define    IBUFSIZE    64    /* this must be a power of 2 */
  219.  
  220. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  221. int in_next = 0;        /* pos to retrieve next input character */
  222. int in_last = 0;        /* pos to place most recent input character */
  223.  
  224. in_init()    /* initialize the input buffer */
  225.  
  226. {
  227.     in_next = in_last = 0;
  228. }
  229.  
  230. in_check()    /* is the input buffer non-empty? */
  231.  
  232. {
  233.     if (in_next == in_last)
  234.         return(FALSE);
  235.     else
  236.         return(TRUE);
  237. }
  238.  
  239. in_put(event)
  240.  
  241. int event;    /* event to enter into the input buffer */
  242.  
  243. {
  244.     in_buf[in_last++] = event;
  245.     in_last &= (IBUFSIZE - 1);
  246. }
  247.  
  248. int in_get()    /* get an event from the input buffer */
  249.  
  250. {
  251.     register int event;    /* event to return */
  252.  
  253.     event = in_buf[in_next++];
  254.     in_next &= (IBUFSIZE - 1);
  255.     return(event);
  256. }
  257.  
  258. /*    Open the terminal
  259.     put it in RA mode
  260.     learn about the screen size
  261.     read TERMCAP strings for function keys
  262. */
  263.  
  264. tcapopen()
  265.  
  266. {
  267.     register int index;        /* general index */
  268.     char *t, *p;
  269.     char tcbuf[1024];
  270.     char *tv_stype;
  271.     char err_str[72];
  272.     char *getenv();
  273.     char *tgetstr();
  274.  
  275.     strcpy(os, "UNIX");
  276.     if ((tv_stype = getenv("TERM")) == NULL) {
  277.         puts(TEXT182);
  278. /*             "Environment variable TERM not defined!" */
  279.         meexit(1);
  280.     }
  281.  
  282.     if ((tgetent(tcbuf, tv_stype)) != 1) {
  283.         sprintf(err_str, TEXT183, tv_stype);
  284. /*                 "Unknown terminal type %s!" */
  285.         puts(err_str);
  286.         meexit(1);
  287.     }
  288.  
  289.  
  290.     if ((term.t_nrow=(short)tgetnum("li")-1) == -1) {
  291.            puts(TEXT184);
  292. /*            "termcap entry incomplete (lines)" */
  293.            meexit(1);
  294.     }
  295.     term.t_mrow =  term.t_nrow;
  296.  
  297.     if ((term.t_ncol=(short)tgetnum("co")) == -1){
  298.         puts(TEXT185);
  299. /*            "Termcap entry incomplete (columns)" */
  300.         meexit(1);
  301.     }
  302.     term.t_mcol = term.t_ncol;
  303.  
  304.     p = tcapbuf;
  305.     t = tgetstr("pc", &p);
  306.     if (t)
  307.         PC = *t;
  308.  
  309.     CL = tgetstr("cl", &p);
  310.     CM = tgetstr("cm", &p);
  311.     CE = tgetstr("ce", &p);
  312.     UP = tgetstr("up", &p);
  313.     SE = tgetstr("se", &p);
  314.     SO = tgetstr("so", &p);
  315.     if (SO != NULL)
  316.         revexist = TRUE;
  317.  
  318.     if (CL == NULL || CM == NULL || UP == NULL)
  319.     {
  320.         puts(TEXT186);
  321. /*             "Incomplete termcap entry\n" */
  322.         meexit(1);
  323.     }
  324.  
  325.     if (CE == NULL)     /* will we be able to use clear to EOL? */
  326.         eolexist = FALSE;
  327.          
  328.     IS = tgetstr("is", &p); /* extract init string */
  329.     KS = tgetstr("ks", &p); /* extract keypad transmit string */
  330.     KE = tgetstr("ke", &p); /* extract keypad transmit end string */
  331.             
  332.     /* read definitions of various function keys into ttable */
  333.     for (index = 0; index < NTBINDS; index++) {
  334.         strcpy(ttable[index].p_seq,
  335.             fixnull(tgetstr(ttable[index].p_name, &p)));
  336.     }
  337.  
  338.     /* tell unix we are goint to use the terminal */
  339.     ttopen();
  340.  
  341.     /* make sure we don't over run the buffer (TOO LATE I THINK) */
  342.     if (p >= &tcapbuf[TCAPSLEN]) {
  343.         puts(TEXT187);
  344. /*             "Terminal description too big!\n" */
  345.         meexit(1);
  346.     }
  347.  
  348.     /* send init strings if defined */
  349.     if (IS != NULL)
  350.         putpad(IS);
  351.  
  352.     if (KS != NULL)
  353.         putpad(KS);
  354.  
  355.     /* initialize the input buffer */
  356.     in_init();
  357. }
  358.  
  359. tcapclose()
  360. {
  361.     /* send end-of-keypad-transmit string if defined */
  362.     if (KE != NULL)
  363.         putpad(KE);
  364.     ttclose();
  365. }
  366.  
  367. tcapkopen()
  368.  
  369. {
  370.     strcpy(sres, "NORMAL");
  371. }
  372.  
  373. tcapkclose()
  374.  
  375. {
  376. }
  377.  
  378. unsigned int extcode(c)
  379.  
  380. unsigned int c;
  381.  
  382. {
  383.     return(c);
  384. }
  385.  
  386. /*    TCAPGETC:    Get on character.  Resolve and setup all the
  387.             appropriate keystroke escapes as defined in
  388.             the comments at the beginning of input.c
  389. */
  390.  
  391. int tcapgetc()
  392.  
  393. {
  394.     int c;        /* current extended keystroke */
  395.  
  396.     /* if there are already keys waiting.... send them */
  397.     if (in_check())
  398.         return(in_get());
  399.  
  400.     /* otherwise... get the char for now */
  401.     c = get1key();
  402.  
  403.     /* unfold the control bit back into the character */
  404.     if (CTRL & c)
  405.         c = (c & ~ CTRL) - '@';
  406.  
  407.     /* fold the event type into the input stream as an escape seq */
  408.     if ((c & ~255) != 0) {
  409.         in_put(0);        /* keyboard escape prefix */
  410.         in_put(c >> 8);        /* event type */
  411.         in_put(c & 255);    /* event code */
  412.         return(tcapgetc());
  413.     }
  414.  
  415.     return(c);
  416. }
  417.  
  418. /*    GET1KEY:    Get one keystroke. The only prefixs legal here
  419.             are the SPEC and CTRL prefixes.
  420.  
  421.     Note:
  422.  
  423.         Escape sequences that are generated by terminal function
  424.         and cursor keys could be confused with the user typing
  425.         the default META prefix followed by other chars... ie
  426.  
  427.         UPARROW  =  <ESC>A   on some terminals...
  428.         apropos  =  M-A
  429.  
  430.         The difference is determined by measuring the time between
  431.         the input of the first and second character... if an <ESC>
  432.         is types, and is not followed by another char in 1/30 of
  433.         a second (think 300 baud) then it is a user input, otherwise
  434.         it was generated by an escape sequence and should be SPECed.
  435. */
  436.  
  437. int PASCAL NEAR get1key()
  438.  
  439. {
  440.     register int c;
  441.     register int index;    /* index into termcap binding table */
  442.     char *sp;
  443. #if    BSD | V7 | HPUX8 | HPUX9
  444.     int fdset;
  445.     struct timeval timeout;
  446. #endif
  447.     char cseq[10];        /* current sequence being parsed */
  448.  
  449.     c = ttgetc();
  450.  
  451.     /* if it is not an escape character */
  452.     if (c != 27)
  453.             return(c);
  454.  
  455.     /* process a possible escape sequence */
  456.     /* set up to check the keyboard for input */
  457. #if    BSD | V7 | HPUX8 | HPUX9
  458.     fdset = 1;
  459.     timeout.tv_sec = 0;
  460.     timeout.tv_usec = 35000L;
  461.  
  462.     /* check to see if things are pending soon */
  463.     if (kbdmode != PLAY &&
  464.         select(1, &fdset, (int *)NULL, (int *)NULL, &timeout) == 0)
  465.         return(CTRL | '[');
  466. #endif
  467.  
  468. #if XENIX | SUNOS
  469.     if ((kbdmode != PLAY) && (rdchk(0) <= 0)) {
  470.         nap(35L);
  471.         if (rdchk(0) <= 0)
  472.             return(CTRL | '[');
  473.     }
  474. #endif
  475.  
  476. #if    USG | AUX | SMOS
  477.     /* we don't know how to do this check for a pending char within
  478.        1/30th of a second machine independantly in the general System V
  479.        case.... so we don't */
  480.     if (kbdmode != PLAY)
  481.         return(CTRL | '[');
  482. #endif
  483.  
  484.     /* a key is pending within 1/30 of a sec... its an escape sequence */
  485.     cseq[0] = 27;
  486.     sp = &cseq[1];
  487.     while (sp < &cseq[6]) {
  488.         c = ttgetc();
  489.         *sp++ = c;
  490.         *sp = 0;
  491.         for (index = 0; index < NTBINDS; index++) {
  492.             if (strcmp(cseq, ttable[index].p_seq) == 0)
  493.                 return(ttable[index].p_code);
  494.         }
  495.     }
  496.     return(SPEC | 0);
  497. }
  498.  
  499. tcapmove(row, col)
  500. register int row, col;
  501. {
  502.     putpad(tgoto(CM, col, row));
  503. }
  504.  
  505. tcapeeol()
  506. {
  507.     putpad(CE);
  508. }
  509.  
  510. tcapeeop()
  511. {
  512.     putpad(CL);
  513. }
  514.  
  515. tcapclrd()
  516. {
  517.     putpad(HO);
  518.     putpad(CL);
  519. }
  520.  
  521. tcaprev(state)        /* change reverse video status */
  522.  
  523. int state;        /* FALSE = normal video, TRUE = reverse video */
  524.  
  525. {
  526. /*    static int revstate = FALSE;*/
  527.  
  528.     if (state) {
  529.         if (SO != NULL)
  530.             putpad(SO);
  531.     } else
  532.         if (SE != NULL)
  533.             putpad(SE);
  534. }
  535.  
  536. tcapcres()    /* change screen resolution */
  537.  
  538. {
  539.     return(TRUE);
  540. }
  541.  
  542. spal(dummy)    /* change palette string */
  543.  
  544. {
  545.     /*    Does nothing here    */
  546. }
  547.  
  548. #if    COLOR
  549. tcapfcol()    /* no colors here, ignore this */
  550. {
  551. }
  552.  
  553. tcapbcol()    /* no colors here, ignore this */
  554. {
  555. }
  556. #endif
  557.  
  558. tcapbeep()
  559. {
  560.     ttputc(BEL);
  561. }
  562.  
  563. putpad(str)
  564. char    *str;
  565. {
  566.     tputs(str, 1, ttputc);
  567. }
  568.  
  569. putnpad(str, n)
  570. char    *str;
  571. {
  572.     tputs(str, n, ttputc);
  573. }
  574.  
  575.  
  576. #if    FLABEL
  577. fnclabel(f, n)        /* label a function key */
  578.  
  579. int f,n;    /* default flag, numeric argument [unused] */
  580.  
  581. {
  582.     /* on machines with no function keys...don't bother */
  583.     return(TRUE);
  584. }
  585. #endif
  586. #else
  587.  
  588. hello()
  589. {
  590. }
  591.  
  592. #endif
  593.